package com.example.common.exception;

import com.example.common.api.ResultUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.bind.support.WebExchangeBindException;
import org.springframework.web.server.ServerWebInputException;

import javax.validation.ConstraintViolationException;
import java.util.concurrent.CompletionException;

/**
 * 统一的异常捕捉
 * */
@RestControllerAdvice
@Slf4j
public class MyExceptionHandler {

    // 统一请求的Validated验证
    @ExceptionHandler(value = {WebExchangeBindException.class})
    public ResultUtil validExceptionHandler(WebExchangeBindException bindException){
        ObjectError error = bindException.getBindingResult().getAllErrors().get(0);
        log.error("验证错误信息：{}", error.getDefaultMessage());
        return ResultUtil.validateFailed(error.getDefaultMessage());
    }

    // 统一请求的Validated验证
    @ExceptionHandler(value = {ServerWebInputException.class})
    public ResultUtil validExceptionHandler(ServerWebInputException exception){
        log.error("传入的参数有误：{}", exception.getMessage());
        return ResultUtil.validateFailed("缺少传参：" + exception.getReason());
    }

    // 统一请求的Validated验证
    @ExceptionHandler(value = {ConstraintViolationException.class})
    public ResultUtil validExceptionHandler(ConstraintViolationException exception){
        log.error("验证错误信息：{}", exception.getMessage());
        return ResultUtil.validateFailed(exception.getMessage());
    }

    // 请求绑定java bean的时候出现错误
    @ExceptionHandler(value = {BindException.class})
    public ResultUtil validExceptionHandler(BindException exception){
        log.error("验证错误信息BindException：{}", exception.getMessage());
        return ResultUtil.validateFailed(exception.getMessage());
    }

    // 报错信息
    @ExceptionHandler(value = {Exception.class})
    public ResultUtil errorExceptionHandler(Exception exception){
        log.error("报错信息：{}", exception.getClass());
        return ResultUtil.validateFailed(exception.getMessage());
    }

    // 请求绑定java bean的时候出现错误
    @ExceptionHandler(value = {CompletionException.class})
    public ResultUtil validExceptionHandler(CompletionException exception){
        log.error("feign在微服务调用失败：{}", exception.getMessage());
        return ResultUtil.validateFailed("微服务调用异常");
    }

    // 校验requestBody中的传参错误
    @ExceptionHandler(value = {MethodArgumentNotValidException.class})
    public ResultUtil validExceptionHandler(MethodArgumentNotValidException exception){
        log.error("校验参数错误：{}", exception.getMessage());
        FieldError error = exception.getBindingResult().getFieldError();
        String field = error.getField();
        String message = String.format("%s:%s", field, error.getDefaultMessage());
        return ResultUtil.validateFailed(message);
    }

}
